#ifndef GDelegate_H
#define GDelegate_H

#include "Global_Signal.h"
#include "Delegates.h"

class SIGNALSHARED_EXPORT Delegate : public AbstractDelegate
{
    public:

    AbstractDelegate * aDelegate;

    template <class T>
    Delegate(int (T::*apDelegate)(), T* ref);                   /*! Delegate0 */

    template <class T, class U>
    Delegate(int (T::*apDelegate)(U), T *ref);                  /*! Delegate1 */

    template <class T, class U, class V>
    Delegate(int (T::*apDelegate)(U,V), T* ref);                /*! Delegate2 */

    template <class T, class U, class V, class W>
    Delegate(int (T::*apDelegate)(U,V,W), T* ref);              /*! Delegate3 */

    template<class T>
    Delegate(int (*apDelegate)(T),T aArg1);                                     /*! sDelegate1 */

    template<class T,class U>
    Delegate(int (*apDelegate)(T,U),T aArg1, U aArg2);                          /*! sDelegate2 */

    template<class T,class U, class W>
    Delegate(int (*apDelegate)(T,U,W),T aArg1, U aArg2, W aArg3);               /*! sDelegate3 */


    virtual void Run();

    template<class T>
     virtual  void Run(T arg)=0;

    template<class T, class U>
     virtual  void Run(T arg, U arg2)=0;

    template<class T, class U, class W>
     virtual  void Run(T arg, U arg2, W arg3)=0;


};

/*! Delegate0 */

template <class T>
Delegate::Delegate(int (T::*apDelegate)(), T * ref){
    aDelegate= new Delegate0<T>(apDelegate,ref);
}

/*! Delegate1 */

template <class T, class U>
Delegate::Delegate(int(T::*apDelegate)(U),T * ref){
    aDelegate = new Delegate1<T,U>(apDelegate, ref);
}

/*! Delegate2*/

template <class T, class U, class V>
Delegate::Delegate(int (T::*apDelegate)(U,V),T * ref){
    aDelegate = new Delegate2<T,U,V>(apDelegate, ref);
}

/*! Delegate3 */

template <class T, class U, class V, class W>
Delegate::Delegate(int (T::*apDelegate)(U,V,W),T * ref){
    aDelegate = new Delegate3<T,U,V,W>(apDelegate, ref);
}

/*! sDelegate1 */

template<class T>
Delegate::Delegate(int (*apDelegate)(T),T aArg1){
   aDelegate=new sDelegate1<T>(apDelegate,aArg1);
}

/*! sDelegate2 */

template<class T,class U>
Delegate::Delegate(int (*apDelegate)(T,U),T aArg1, U aArg2){
     aDelegate=new sDelegate2<T,U>(apDelegate,aArg1,aArg2);
}

/*! sDelegate3 */

template<class T,class U, class W>
Delegate::Delegate(int (*apDelegate)(T,U,W),T aArg1, U aArg2, W aArg3){
    aDelegate=new sDelegate3<T,U,W>(apDelegate,aArg1,aArg2,aArg3);
}

virtual void Delegate::Run(){
    aDelegate->Run();
}

template<class T>
 virtual  void Delegate::Run(T arg){
    aDelegate->Run(arg);
}

template<class T, class U>
 virtual  void Delegate::Run(T arg, U arg2){
    aDelegate->Run(arg1, arg2);
}

template<class T, class U, class W>
 virtual  void Delegate::Run(T arg, U arg2, W arg3){
    aDelegate->Run(arg1, arg2, arg3);
}



#endif // GDelegate_H
